#include <stdio.h>
#include <stdlib.h>

#include "manipulation_cases.h"



/* minimum de deux unsigned int */
static unsigned int minimum(const unsigned int a, const unsigned int b)
{
    if(a < b)
        return a;
    else
        return b;
}


/* maximum de deux unsigned int */
static unsigned int maximum(const unsigned int a, const unsigned int b)
{
    if(a > b)
        return a;
    else
        return b;
}



void init_tab_dyn_cases_constantes(struct tab_dyn_cases_constantes* tab, const unsigned int taille)
{
    tab->nb_elements = 0;
    if(!(tab->tab = (struct case_constante*)malloc(taille * sizeof(struct case_constante))))
        exit(EXIT_MALLOC);
}




void ajouter_case_constante(struct tab_dyn_cases_constantes* tab, const struct case_constante* type_case_constante)
{
    tab->tab[tab->nb_elements] = *type_case_constante;
    tab->nb_elements++;
}



void detruire_tab_dyn_cases_constantes(struct tab_dyn_cases_constantes* tab)
{
    if(tab->nb_elements > 0)
        free(tab->tab);
}



struct case_constante* get_case_constante_liste_types(const struct carte_zone* carte, const unsigned char n)
{
    return &carte->liste_infos_cases_constantes.tab[n];
}




void set_case_constante_grille(struct carte_zone* carte, const unsigned char type_case,
                               const unsigned int x, const unsigned int y)
{
    carte->grille_cases_constantes[x + y * carte->dim_x] = type_case;
}




void remplir_rectangle_cases_constantes(struct carte_zone* carte, unsigned char type_case,
                                        const unsigned int x_min, const unsigned int y_min,
                                        const unsigned int x_max, const unsigned int y_max)
{
    int i, j;

    /*
     * la fonction est capable de tracer le rectangle meme si ses coordonnees
     * sont donnees dans le desordre
     */
    for(j = minimum(y_min, y_max);  j <= maximum(y_min, y_max);  j++)
        for(i = minimum(x_min, x_max);  i <= maximum(x_min, x_max);  i++)
            set_case_constante_grille(carte, type_case, i, j);
}



void set_case_destructible_grille(struct carte_zone* carte, const struct case_destructible* donnees_case,
                                  const unsigned int x, const unsigned int y)
{
    struct case_destructible* p_case;

    if(donnees_case)
    {
        /*
         * si la case contenait deja un element destructible,
         * il ne faut pas faire de nouveau malloc !
         */
        if(!(p_case = carte->grille_cases_destructibles[x + y * carte->dim_x]))
            if(!(p_case = (struct case_destructible*)malloc(sizeof(struct case_destructible))))
                exit(EXIT_MALLOC);
        carte->grille_cases_destructibles[x + y * carte->dim_x] = p_case;
        *p_case = *donnees_case;
    }
    else
        carte->grille_cases_destructibles[x + y * carte->dim_x] = NULL;
}




void remplir_rectangle_cases_destructibles(struct carte_zone* carte, const struct case_destructible* donnees_case,
                                           const unsigned int x_min, const unsigned int y_min,
                                           const unsigned int x_max, const unsigned int y_max)
{
    int i, j;

    /*
     * ici encore, la fonction est capable de tracer le rectangle
     * meme si ses coordonnees sont donnees dans le desordre
     */
    for(j = minimum(y_min, y_max);  j <= maximum(y_min, y_max);  j++)
        for(i = minimum(x_min, x_max);  i <= maximum(x_min, x_max);  i++)
            set_case_destructible_grille(carte, donnees_case, i, j);
}



struct case_constante* get_case_constante_grille(const struct carte_zone* carte,
                                                 const unsigned int x, const unsigned int y)
{
    unsigned char indice;

    indice = carte->grille_cases_constantes[x + y * carte->dim_x];
    return get_case_constante_liste_types(carte, indice);
}



struct case_destructible* get_case_destructible(const struct carte_zone* carte, const unsigned int x, const unsigned int y)
{
    return carte->grille_cases_destructibles[x + y * carte->dim_x];
}



void endommager_case_destructible(struct carte_zone* carte, unsigned int x, unsigned int y)
{
    struct case_destructible* p_case_destructible;

    /*
     * des degats sont causes a la case !
     * Si ses points de vie atteignent 0...
     */
    p_case_destructible = get_case_destructible(carte, x, y);
    if(!(--p_case_destructible->pv_case))
    {
        /*
         * ...il faut detruire toutes
         * les cases de son groupe si necessaire
         * (un id de groupe a 0 signifie que l'element
         * est independant)
         */
        if(p_case_destructible->groupe)
            detruire_cases_groupe(carte, p_case_destructible->groupe);
        else
        {
            free(p_case_destructible);
            set_case_destructible_grille(carte, NULL, x, y);
        }
    }
}



void detruire_cases_groupe(struct carte_zone* carte, const unsigned int num_groupe)
{
    int i, j;
    struct case_destructible* p_case_destructible;

    /*
     * pas besoin de verifier les bords de la carte, car ils contiennent le
     * mur d'enceinte. On economise ainsi un peu de temps !
     */
    for(j = 1;  j < carte->dim_y - 1;  j++)
        for(i = 1;  i < carte->dim_x - 1;  i++)
        {
            p_case_destructible = get_case_destructible(carte, i, j);
            if((p_case_destructible) && p_case_destructible->groupe == num_groupe)
            {
                free(p_case_destructible);
                set_case_destructible_grille(carte, NULL, i, j);
            }
        }
}

